#include "StdAfx.h"
#include "SoundBank.h"
#include "WaveSample.h"

#ifdef _DEBUG
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#endif

SoundBank::SoundBank(void)
{
	dest = new char[25];
}

SoundBank::~SoundBank(void)
{
	StringSoundMap::iterator iterator = soundMap.begin();
	while(iterator!=soundMap.end())
	{
		delete iterator->second;
		iterator++;
	}
	soundMap.clear();
	delete dest;
}

WaveSample* SoundBank::GetWaveSample(std::string& name)
{
	WaveSample* sound = NULL;
	StringSoundMap::iterator iterator = soundMap.find(name);
	if(iterator!=soundMap.end())
	{
		sound = iterator->second;
	}
	return sound;
}

void SoundBank::AddWaveSample(WaveSample* sound)
{
	soundMap[sound->name] = sound;
}

static const char* randomName = "random";
static const char* sawtoothName = "sawtooth";
static const char* sineName = "sine";
static const char* squareName = "square";
static const char* triangularName = "triangular";
static const char* userFunc1Name = "user1";
static const char* userFunc2Name = "user2";
static const char* userFunc3Name = "user3";

char* SoundBank::SampleName(WaveForm waveForm, int frequency, double intensity)
{
	const char* waveName = NULL;
	switch(waveForm)
	{
	case Random:
		waveName = randomName;
		break;
	case Sawtooth:
		waveName = sawtoothName;
		break;
	case Sine:
		waveName = sineName;
		break;
	case Square:
		waveName = squareName;
		break;
	case Triangular:
		waveName = triangularName;
		break;
	case UserFunc1:
		waveName = userFunc1Name;
		break;
	case UserFunc2:
		waveName = userFunc2Name;
		break;
	case UserFunc3:
		waveName = userFunc3Name;
		break;
	}
	if(intensity<=0 || intensity>1)
	{
		intensity = 0;
	}
	sprintf(dest, "freq %d int %.1f %s", frequency, intensity, waveName);
	return dest;
}

WaveSample* SoundBank::GetWaveSample(WaveForm waveForm, int frequency, int rate)
{
	char* nameP = SampleName(waveForm, frequency, -1);
	std::string name = nameP;
	//delete nameP;
	WaveSample* sample = GetWaveSample(name);
	if(sample==NULL)
	{		
		switch(waveForm)
		{
		case Random:
			sample = WaveSample::RandomSample(name, frequency, rate);
			break;
		case Sawtooth:
			sample = WaveSample::SawtoothSample(name, frequency, rate);
			break;
		case Sine:
			sample = WaveSample::SineSample(name, frequency, rate);
			break;
		case Square:
			sample = WaveSample::SquareSample(name, frequency, rate);
			break;
		case Triangular:
			sample = WaveSample::TriangularSample(name, frequency, rate);
			break;
		}
		AddWaveSample(sample);
	}
	return sample;
}

WaveSample* SoundBank::GetWaveSample(WaveForm waveForm, void(*WaveSampleCb)(WaveSample*), int frequency, int rate)
{
	char* nameP = SampleName(waveForm, frequency, -1);
	std::string name = nameP;
	//delete nameP;
	WaveSample* sample = GetWaveSample(name);
	if(sample==NULL)
	{		
		sample = WaveSample::CreateSample(name, frequency, rate, WaveSampleCb);
		AddWaveSample(sample);
	}
	return sample;
}

WaveSample* SoundBank::GetWaveSample(WaveForm waveForm, int frequency, int rate, double intensity)
{
	char* nameP = SampleName(waveForm, frequency, intensity);
	std::string name = nameP;
	//delete nameP;
	WaveSample* sample = GetWaveSample(name);
	if(sample==NULL)
	{
		WaveSample* baseSample = GetWaveSample(waveForm, frequency, rate);
		short* sampleBuf = new short[baseSample->length];
		register int i=0;
		for(; i<baseSample->length; i++)
		{
			sampleBuf[i] = (double)baseSample->data[i]*intensity;
		}
		sample = new WaveSample(name, sampleBuf, baseSample->length, rate, frequency);
		AddWaveSample(sample);
	}
	return sample;
}

WaveSample* SoundBank::GetWaveSample(WaveForm waveForm, void(*WaveSampleCb)(WaveSample*), int frequency, int rate, double intensity)
{
	char* nameP = SampleName(waveForm, frequency, intensity);
	std::string name = nameP;
	//delete nameP;
	WaveSample* sample = GetWaveSample(name);
	if(sample==NULL)
	{
		WaveSample* baseSample = GetWaveSample(waveForm, WaveSampleCb, frequency, rate);
		short* sampleBuf = new short[baseSample->length];
		register int i=0;
		for(; i<baseSample->length; i++)
		{
			sampleBuf[i] = (double)baseSample->data[i]*intensity;
		}
		sample = new WaveSample(name, sampleBuf, baseSample->length, rate, frequency);
		AddWaveSample(sample);
	}
	return sample;
}